#include "QFile"
#include "QString"
#include "QTextStream"
#include "QStringList"
#include "definitions.h"
#include "map.h"
#include "engine.h"
#include "minion.h"
#include "../GameAI/gameai.h"

enum MapSection
{
    GLOBAL,
    TEAM,
    MINION
};

Map::Map(const QString &Filename)
{
    SpawnPeriod = 0;
    SpawnTimeLeft = 0;

    QFile file(Filename);
    QString line;
    if(file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        MapSection Section = GLOBAL;
        QTextStream stream(&file);
        while(!stream.atEnd())
        {
            line = stream.readLine();
            int pos = line.indexOf(":");
            if(pos == -1) continue;

            QString parameter = line.mid(0, pos);
            QString value = line.mid(pos + 1);

            switch(Section)
            {
            case GLOBAL:
                if(parameter == "Background") Background = Engine::LoadPicture(value);
                else if(parameter == "SpawnPeriod") SpawnPeriod = value.toInt();
                else if(parameter == "InitialSpawn") SpawnTimeLeft = value.toInt();
                else if(parameter == "Obstacle") ProcessObstacle(value);
                else if(parameter == "Team")
                {
                    Teams.append(TeamSettings());
                    Section = TEAM;
                }
                break;
            case TEAM:
                if(parameter == "Respawn") ProcessRespawn(value);
                else if(parameter == "Miniminion")
                {
                    ProcessMiniminion(value);
                    Section = MINION;
                }
                else if(parameter == "Tower") ProcessTower(value);
                else if(parameter == "DefaultOrientation") ProcessDefaultOrientation(value);
                else if(value == "End") Section = GLOBAL;
                break;
            case MINION:
                if(parameter == "Spawn") ProcessMinionSpawn(value);
                else if(parameter == "Route") ProcessMinionRoute(value);
                else if(value == "End") Section = TEAM;
                break;
            }
        }
    }

    SpawnTimeLeft *= Engine::TicksPerSecond;
}

void Map::ProcessObstacle(const QString &value)
{
    QStringList coordinates = value.split(",");
    if(coordinates.count() != 4) return;
    Obstacles.append(QRect(coordinates[0].toInt(),
                           coordinates[1].toInt(),
                           coordinates[2].toInt(),
                           coordinates[3].toInt()));
}

void Map::ProcessRespawn(const QString &value)
{
    QStringList list = value.split(",");
    if(list.count() != 2) return;
    Teams.last().RespawnPoints.append(QPoint(list[0].toInt(), list[1].toInt()));
}

void Map::ProcessMiniminion(const QString &value)
{
    MiniMinion m;
    m.Filename = value;
    Teams.last().MiniSpawnPoints.append(m);
}

void Map::ProcessTower(const QString &value)
{
    QStringList list = value.split(",");
    if(list.count() != 3) return;

    Engine::SpawnMinion(list[0], Teams.count(), list[1].toInt(), list[2].toInt(),
            Teams.last().DefaultOrientation);
}

void Map::ProcessDefaultOrientation(const QString &value)
{
    Teams.last().DefaultOrientation = value.toDouble();
}

void Map::ProcessMinionSpawn(const QString &value)
{
    QStringList list = value.split(",");
    if(list.count() != 2) return;
    Teams.last().MiniSpawnPoints.last().SpawnPoint = QPoint(list[0].toInt(), list[1].toInt());
}

void Map::ProcessMinionRoute(const QString &value)
{
    QStringList list = value.split(",");
    if(list.count() != 2) return;
    Teams.last().MiniSpawnPoints.last().Route.append(QPoint(list[0].toInt(), list[1].toInt()));
}

void Map::Tick()
{
    if(SpawnTimeLeft > 0) SpawnTimeLeft--;
    else
    {
        for(int team=0; team < Teams.count(); team++)
        {
            for(int point=0; point < Teams[team].MiniSpawnPoints.count(); point++)
            {
                Minion *NewMini = Engine::SpawnMinion(
                            Teams[team].MiniSpawnPoints[point].Filename, team+1,
                            Teams[team].MiniSpawnPoints[point].SpawnPoint.x(),
                            Teams[team].MiniSpawnPoints[point].SpawnPoint.y(),
                            Teams[team].DefaultOrientation);

                GameAI::AddAI(NewMini, Teams[team].MiniSpawnPoints[point].Route);
            }
        }
        SpawnTimeLeft = SpawnPeriod * Engine::TicksPerSecond;
    }
}

QPixmap *Map::GetBackground() { return Background; }

double Map::GetTeamDefaultOrientation(unsigned int team)
{
    team--;
    if(team >= (unsigned int)Teams.count())
        return 0.0;
    else
        return Teams[team].DefaultOrientation;
}
